package com.jin.webvideo.base.rpc;

import org.apache.http.client.HttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;

public class RpcFactoryBean<T> implements FactoryBean<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(RpcFactoryBean.class);

    private final Class<T> rpcInterface;
    private final String prefix;
    private String[] header;
    private HttpClient httpClient;
    private Environment environment;

    public RpcFactoryBean(Class<T> rpcInterface) {
        this.rpcInterface = rpcInterface;
        RpcInterface annotation = AnnotationUtils.getAnnotation(rpcInterface, RpcInterface.class);
        this.prefix = annotation.prefix();
        this.header = annotation.headers();
        LOGGER.debug("create new RpcFactoryBean prefix={} headers={}", prefix, header);
    }

    public void setHttpClient(HttpClient httpClient) {
        this.httpClient = httpClient;
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public Class<?> getObjectType() {
        return this.rpcInterface;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public T getObject() throws Exception {
        Enhancer enhancer = new Enhancer();
        // 设置目标类的字节码文件
        enhancer.setInterfaces(new Class[]{rpcInterface});
        if (this.header.length == 1) {
            this.header = this.environment.resolveRequiredPlaceholders(this.header[0]).split(",");
        }
        RpcMethodInterceptor interceptor = new RpcMethodInterceptor(httpClient, environment.resolvePlaceholders(this.prefix), this.header);
        // 设置回调函数
        enhancer.setCallback(interceptor);
        // create方法正式创建代理类
        LOGGER.debug("create new interface proxy interceptor={}", interceptor);
        return (T)enhancer.create();
    }
}
